package com.file.word;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.aspose.words.Font;
import com.aspose.words.*;
import com.file.other.DocumentAnalysisEntity;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author: cxt
 * @date: 2023/7/4 22:45
 */
@Slf4j
@RestController
@RequestMapping("/asposeWorld")
public class AsposeWorldUtil {
    /**
     * @param info info
     * @return void
     * @description 一步去解析
     * @title analysisStyle
     * @author cxt
     * @date: 2023/6/9
     */
    @PostMapping("/analysisStyle")
    public void analysisStyle(DocumentAnalysisEntity info, String url) {
        WordLib.setUnlimitedLicense();
        int tableCount = 0;
        try {
            ArrayList<DocumentAnalysisEntity> list = new ArrayList<>();
            // 文档树，树中有节点
            Document document = new Document(url);
            NodeCollection<Section> sectionList = document.getSections();
            // 遍历分节
            for (int i = 0; i < sectionList.getCount(); i++) {
                Section section = (Section) sectionList.get(i);
                // 遍历分节下的节点，节点组成有：主体(BODY)、段落(PARAGRAPH)、表示一段连续的文本(RUN)、表示一个表格(TABLE)、表格中一行(ROW)、表格中一个单元格(CELL)……
                NodeCollection<Node> nodeList = section.getChildNodes(NodeType.PARAGRAPH, true);
                for (int j = 0; j < nodeList.getCount(); j++) {
                    // 段落
                    Paragraph paragraph = (Paragraph) nodeList.get(j);
                    //获取文档内容
                    String paragraphContent = paragraph.getText().trim();
                    if (StringUtils.isBlank(paragraphContent)) {
                        continue;
                    }
                    JSONObject styleJSON = new JSONObject();
                    Font breakFont = paragraph.getParagraphBreakFont();
                    styleJSON.put("font", fontStyle(breakFont));
                    ParagraphFormat format = paragraph.getParagraphFormat();
                    // 大纲级别
                    int level = format.getOutlineLevel();
                    styleJSON.put("paragraph", paragraphStyle(format));
                    // 样式名称
                    styleJSON.put("styleName", format.getStyle().getName());

                    // 样式的值
                    String styleValue = styleJSON.toJSONString();


                    String mainId = RandomUtil.randomString(20);
                    // 标题
                    if (level < 9) {
                        // ParagraphFormat format = document.getStyles().get(styleValue).getParagraphFormat();
                        String styleName = (level + 1) + "级标题";
                        list.add(new DocumentAnalysisEntity(mainId, info.getId(), styleName, styleValue));
                        continue;
                    }

                    Table table = null;
                    switch (paragraphContent) {
                        case "表题文字":
                            list.add(new DocumentAnalysisEntity(mainId, info.getId(), "表题文字", styleValue));
                            break;
                        case "图题文字":
                            list.add(new DocumentAnalysisEntity(mainId, info.getId(), "图题文字", styleValue));
                            break;
                        case "图片公式居中":
                            list.add(new DocumentAnalysisEntity(mainId, info.getId(), "图片公式居中", styleValue));
                            break;
                        case "表格文字":
                            list.add(new DocumentAnalysisEntity(mainId, info.getId(), "表格文字", styleValue));
                            table = (Table) document.getChildNodes(NodeType.TABLE, true).get(tableCount);
                            if (null != table) {
                                tableCount++;
                                List<DocumentAnalysisEntity> analysis = tableAnalysis(table, info, "正文");
                                list.addAll(analysis);
                            }
                            break;
                        case "附录":
                            list.add(new DocumentAnalysisEntity(mainId, info.getId(), "附录", styleValue));
                            break;
                        case "附录文字":
                            list.add(new DocumentAnalysisEntity(mainId, info.getId(), "附录文字", styleValue));
                            break;
                        case "附录-表格文字":
                            list.add(new DocumentAnalysisEntity(mainId, info.getId(), "附录-表格文字", styleValue));
                            table = (Table) document.getChildNodes(NodeType.TABLE, true).get(tableCount);
                            if (null != table) {
                                tableCount++;
                                List<DocumentAnalysisEntity> analysis = tableAnalysis(table, info, "附录");
                                list.addAll(analysis);
                            }
                            break;
                        case "附录-表题文字":
                            list.add(new DocumentAnalysisEntity(mainId, info.getId(), "附录-表题文字", styleValue));
                            break;
                        case "附录-图题文字":
                            list.add(new DocumentAnalysisEntity(mainId, info.getId(), "附录-图题文字", styleValue));
                            break;
                        case "附录-图片文字":
                            list.add(new DocumentAnalysisEntity(mainId, info.getId(), "附录-图片文字", styleValue));
                            break;
                        case "表头文字":
                            list.add(new DocumentAnalysisEntity(mainId, info.getId(), "表头文字", styleValue));
                            break;
                        case "正文标题":
                            list.add(new DocumentAnalysisEntity(mainId, info.getId(), "正文标题", styleValue));
                            break;
                        case "正文副标题":
                            list.add(new DocumentAnalysisEntity(mainId, info.getId(), "正文副标题", styleValue));
                            break;
                        case "正文":
                            list.add(new DocumentAnalysisEntity(mainId, info.getId(), "正文", styleValue));
                            break;
                        case "前言":
                            list.add(new DocumentAnalysisEntity(mainId, info.getId(), "前言", styleValue));
                            break;
                        case "前言内容":
                            list.add(new DocumentAnalysisEntity(mainId, info.getId(), "前言内容", styleValue));
                            break;
                    }
                }
            }
            List<DocumentAnalysisEntity> uniqueDocumentStyles = new ArrayList<>(list.stream().collect(Collectors.toMap(DocumentAnalysisEntity::getStyleName, documentStyle -> documentStyle, (documentStyle1, documentStyle2) -> documentStyle1)).values());
            // 插入到数据库中去
            System.out.println(uniqueDocumentStyles);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @param table table
     * @param info  info
     * @return List<km.entity.DocumentAnalysisEntity>
     * @description 表格样式解析，共用
     * @title tableAnalysis
     * @author cxt
     * @date: 2023/6/9
     */
    public List<DocumentAnalysisEntity> tableAnalysis(Table table, DocumentAnalysisEntity info, String tag) {

        ArrayList<DocumentAnalysisEntity> list = new ArrayList<>();
        try {
            RowCollection rows = table.getRows();
            Row row = rows.get(0);
            CellCollection cells = row.getCells();
            Cell cell = cells.get(0);

            // 表头字体样式
            String content = cell.getText().trim();
            if (content.contains("表头")) {
//                CellFormat cellFormat = cell.getCellFormat();
                // cell.getFirstParagraph().getParagraphBreakFont()
                // 行高，行距，

                Paragraph paragraph = cell.getFirstParagraph();
                Run run = paragraph.getRuns().get(0);
                Font font = run.getFont();
                JSONObject jsonObject = fontStyle(font);
                double rowHeight = cell.getParentRow().getRowFormat().getHeight();
                int alignment = paragraph.getParagraphFormat().getAlignment();
                // 这里添加表头中其它样式
                jsonObject.put("rowHeight", rowHeight);
                jsonObject.put("alignment", alignment);
                list.add(new DocumentAnalysisEntity(RandomUtil.randomString(20), info.getId(), "表头文字", jsonObject.toJSONString()));
            }

            Border rowTop = row.getRowFormat().getBorders().getTop();
            Border rowRight = row.getRowFormat().getBorders().getRight();
            Border rowbottom = row.getRowFormat().getBorders().getBottom();
            Border rowLeft = row.getRowFormat().getBorders().getLeft();
            JSONArray jsonArray = new JSONArray();
            jsonArray.add(analysisTableStyles(rowTop));
            jsonArray.add(analysisTableStyles(rowbottom));
            jsonArray.add(analysisTableStyles(rowLeft));
            jsonArray.add(analysisTableStyles(rowRight));

            list.add(new DocumentAnalysisEntity(RandomUtil.randomString(20), info.getId(), tag + "表格外边框样式", jsonArray.toJSONString()));

            // 内边框样式开始
            Border right = cell.getCellFormat().getBorders().getRight();
            Border bottom = cell.getCellFormat().getBorders().getBottom();

            JSONArray jsonArray2 = new JSONArray();
            jsonArray2.add(analysisTableStyles(right));
            jsonArray2.add(analysisTableStyles(bottom));

            list.add(new DocumentAnalysisEntity(RandomUtil.randomString(20), info.getId(), tag + "表格内边框样式", jsonArray2.toJSONString()));

            // 表格底纹样式
            Color firstColor = cell.getCellFormat().getShading().getBackgroundPatternColor();
            //  Color color8 = cell.getCellFormat().getShading().getForegroundPatternColor();

            Row secondRow = rows.get(1);
            Cell secondCell = secondRow.getCells().get(0);
            Color secondColor = secondCell.getCellFormat().getShading().getBackgroundPatternColor();
            // 表格字体样式
            // 表头字体样式
            String secondContent = secondCell.getText().trim();
            if (secondContent.contains("表格")) {
                // CellFormat cellFormat = secondCell.getCellFormat();
                // 行高，行距，
                Paragraph paragraph = secondCell.getFirstParagraph();
                Run run = paragraph.getRuns().get(0);
                Font font = run.getFont();
                JSONObject jsonObject = fontStyle(font);
                double rowHeight = secondCell.getParentRow().getRowFormat().getHeight();
                int alignment = paragraph.getParagraphFormat().getAlignment();
                // 这里添加表头中其它样式
                jsonObject.put("rowHeight", rowHeight);
                jsonObject.put("alignment", alignment);
                list.add(new DocumentAnalysisEntity(RandomUtil.randomString(20), info.getId(), "表格文字", jsonObject.toJSONString()));
            }

            JSONArray jsonArray3 = new JSONArray();
            jsonArray3.add(firstColor);
            jsonArray3.add(secondColor);

            list.add(new DocumentAnalysisEntity(RandomUtil.randomString(20), info.getId(), tag + "表格底纹颜色", jsonArray3.toJSONString()));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

    /**
     * @param border border
     * @return alibaba.fastjson.JSONObject
     * @description 解析表格样式
     * @title analysisTableStyles
     * @author cxt
     * @date: 2023/7/6
     */
    public JSONObject analysisTableStyles(Border border) {
        JSONObject jsonTop = new JSONObject();
        jsonTop.put("lineStyle", border.getLineStyle());
        jsonTop.put("lineWidth", border.getLineWidth());
        jsonTop.put("color", border.getColor());
        return jsonTop;
    }

    /**
     * @param font font
     * @return alibaba.fastjson.JSONObject
     * @description 字体样式解析封装
     * @title fontStyle
     * @author cxt
     * @date: 2023/6/30
     */
    public JSONObject fontStyle(Font font) {
        JSONObject contentStyle = new JSONObject();
        contentStyle.put("name", font.getName());
        contentStyle.put("size", font.getSize());
        contentStyle.put("color", font.getColor());
        contentStyle.put("bold", font.getBold());
        contentStyle.put("italic", font.getItalic());
        contentStyle.put("underline", font.getUnderline());
        return contentStyle;
    }

    /**
     * @param format format
     * @return alibaba.fastjson.JSONObject
     * @description 段落样式解析封装
     * @title paragraphStyle
     * @author cxt
     * @date: 2023/6/30
     */
    public JSONObject paragraphStyle(ParagraphFormat format) {
        JSONObject paragraphStyle = new JSONObject();
        // 大纲级别
        paragraphStyle.put("outlineLevel", format.getOutlineLevel());
        // 对齐方式
        paragraphStyle.put("alignment", format.getAlignment());
        // 方向：默认是从做向右
        paragraphStyle.put("bidi", format.getBidi());
        // 左右缩进
        paragraphStyle.put("leftIndent", format.getLeftIndent());
        paragraphStyle.put("rightIndent", format.getRightIndent());
        // 特殊格式：首行缩进
        // getCharacterUnitFirstLineIndent
        paragraphStyle.put("firstLineIndent", format.getFirstLineIndent());
        // 特殊格式：悬挂缩进
        paragraphStyle.put("hangingPunctuation", format.getHangingPunctuation());
        // 是否定义了网络
        paragraphStyle.put("snapToGrid", format.getSnapToGrid());
        // 段前段后
        // getCharacterUnitRightIndent
        paragraphStyle.put("spaceBefore", format.getSpaceBefore());
        paragraphStyle.put("spaceAfter", format.getSpaceAfter());
        // 行距
        paragraphStyle.put("lineSpacingRule", format.getLineSpacingRule());
        // 行距值
        paragraphStyle.put("lineSpacing", format.getLineSpacing());
        // 孤行控制
        paragraphStyle.put("widowControl", format.getWidowControl());
        // 是否与下一段保持在同一页
        paragraphStyle.put("keepWithNext", format.getKeepWithNext());
        // 是否保持在同一页(段中不分页)
        paragraphStyle.put("keepTogether", format.getKeepTogether());
        // 段前分页
        paragraphStyle.put("pageBreakBefore", format.getPageBreakBefore());
        // 自动调整中文与西文的间距
        paragraphStyle.put("addSpaceBetweenFarEastAndAlpha", format.getAddSpaceBetweenFarEastAndAlpha());
        // 自动调整中文与数字的间距
        paragraphStyle.put("addSpaceBetweenFarEastAndDigit", format.getAddSpaceBetweenFarEastAndDigit());
        // 是否显示行号
        paragraphStyle.put("suppressLineNumbers", format.getSuppressLineNumbers());
        // 自动换行
        paragraphStyle.put("wordWrap", format.getWordWrap());
        return paragraphStyle;
    }


    /**
     * @param filePath filePath
     * @return void
     * @description 本地样式解析
     * @title styleAnalysis
     * @author cxt
     * @date: 2023/6/29
     */
    public List<DocumentAnalysisEntity> localAnalysis(String filePath) {
        WordLib.setUnlimitedLicense();
        Document document = null;
        ArrayList<DocumentAnalysisEntity> list = new ArrayList<>();
        try {
            document = new Document(filePath);
            NodeCollection<Section> sectionList = document.getSections();
            // 遍历分节
            for (int i = 0; i < sectionList.getCount(); i++) {
                Section section = (Section) sectionList.get(i);
                // 遍历分节下的节点，节点组成有：主体(BODY)、段落(PARAGRAPH)、表示一段连续的文本(RUN)、表示一个表格(TABLE)、表格中一行(ROW)、表格中一个单元格(CELL)……
                NodeCollection<Node> nodeList = section.getChildNodes(NodeType.PARAGRAPH, true);
                for (int j = 0; j < nodeList.getCount(); j++) {
                    JSONObject styleJSON = new JSONObject();
                    // 段落
                    Paragraph paragraph = (Paragraph) nodeList.get(j);

                    Font breakFont = paragraph.getParagraphBreakFont();
                    styleJSON.put("font", fontStyle(breakFont));

                    // 大纲级别
                    int level = paragraph.getParagraphFormat().getOutlineLevel();

                    ParagraphFormat format = paragraph.getParagraphFormat();
                    styleJSON.put("paragraph", paragraphStyle(format));
                    // 样式名称
                    styleJSON.put("styleName", format.getStyle().getName());


                    Style dstStyle = paragraph.getParagraphFormat().getStyle();
                    // 如果没有，就创建一个新的样式
                    if (dstStyle == null) {
                        continue;
                    }
                    // 字体样式
                    // styleJSON.put("fontStyle", fontStyle(dstStyle.getFont()));

                    //获取文档内容
                    String paragraphContent = paragraph.getText().trim();
                    if (StringUtils.isBlank(paragraphContent)) {
                        continue;
                    }

                    // 样式的名称，Normal，正文，标题等
                    String styleValue = paragraph.getParagraphFormat().getStyleName();
                    System.out.println(styleValue); // TODO 样式值

                    // 对齐
                    //  int alignment = paragraph.getParagraphFormat().getAlignment();

                    String mainId = RandomUtil.randomString(20);
                    // 标题
                    if (level < 9) {
                        // ParagraphFormat format = document.getStyles().get(styleValue).getParagraphFormat();
                        String styleName = (level + 1) + "级标题";
                        // list.add(new DocumentAnalysisEntity(mainId, "0000121", styleName, styleValue));
                        list.add(new DocumentAnalysisEntity(mainId, "0000121", styleName, styleJSON.toJSONString()));
                        continue;
                    }

                    list.add(new DocumentAnalysisEntity(mainId, "0000121", paragraphContent, styleJSON.toJSONString()));

                    // 测试将指定内容修改成指定样式
                    if ("测试的标题".equals(paragraphContent)) {
                        Optional<DocumentAnalysisEntity> firstMatch = list.stream().filter(item -> "3级标题".equals(item.getStyleName())).findFirst();
                        if (firstMatch.isPresent()) {
                            String newStyleValue = firstMatch.get().getStyleValue(); // 从库里取出来的模板数据
                            ParagraphFormat paragraphFormat = paragraph.getParagraphFormat();
                            // 引入预定义的样式，修改标题样式要先获取样式在修改
                            paragraphFormat.setStyleIdentifier(StyleIdentifier.HEADING_2);
                            paragraph.getRuns().get(0).getFont().setColor(Color.pink);
                            paragraph.getRuns().get(0).getFont().setSize(15.6);
                        }
                    }
                }
            }
//            document.save("D:/testsss.docx");
//            document.save("D:/testsss.html", SaveFormat.HTML);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return list;
    }

    @GetMapping("/exportWorld")
    public void exportWorld(HttpServletResponse response) {
        try {
            Document doc = new Document();
            // 创建一个DocumentBuilder对象
            DocumentBuilder builder = new DocumentBuilder(doc);
            builder.getParagraphFormat().setAlignment(ParagraphAlignment.CENTER);
            builder.writeln("一个测试的表格");
            // 创建一个表格
            builder.startTable();
            builder.insertCell();
            // 设置单元格中的文字内容居中
            builder.getCellFormat().setVerticalAlignment(CellVerticalAlignment.CENTER);
            // 设置表格的底色，但是会设置全部的
            builder.getCellFormat().getShading().setBackgroundPatternColor(Color.YELLOW);
            builder.write("名称");
            builder.insertCell();
            builder.getCellFormat().getShading().setBackgroundPatternColor(Color.white);
            builder.write("张章哈");
            builder.insertCell();
            builder.getCellFormat().getShading().setBackgroundPatternColor(Color.YELLOW);
            builder.write("性别");
            builder.insertCell();
            builder.getCellFormat().getShading().setBackgroundPatternColor(Color.white);
            builder.write("男");
            builder.endRow();

            builder.insertCell();
            builder.write("年龄");
            builder.insertCell();
            builder.write("22");
            builder.insertCell();
            builder.write("住址");
            builder.insertCell();
            builder.write("地球中国村");
            builder.endRow();
            builder.endTable();

            // 将表格写入Word文件
            String filename = "output.docx";
            doc.save(filename);

            Path filePath = Paths.get(filename);
            if (!Files.exists(filePath)) {
                return;
            }
            response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
            response.setHeader("Content-Disposition", String.format("attachment; filename=\"%s\"", filename));
            response.setHeader("Pragma", "no-cache");
            response.setHeader("Expires", "0");

            // 写入文件内容
            InputStream is = Files.newInputStream(filePath);
            OutputStream os = response.getOutputStream();
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = is.read(buffer)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.flush();

            // 删除文件
            Files.delete(filePath);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
